home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
tpkbd10.zip
/
KEYBOARD.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1991-07-08
|
27KB
|
789 lines
unit keyboard;
(*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*)
(* *)
(* Turbo Pascal E-Z keyboard interface unit; contains a greatly enhanced *)
(* readkey function (getkey), error-free numeric input routines for *)
(* inputting signed and unsigned integers and real numbers (readint, *)
(* readno, and readreal), string input procedures with line editing and *)
(* and the ability to limit input width (readstr and editstr), and many *)
(* handy miscellaneous routines. Does not use the CRT unit; requires a *)
(* compatible BIOS. *)
(* *)
(* Author: Tom Swingle *)
(* *)
(* Author can be contacted via e-mail at: *)
(* tswingle@oucsace.cs.ohiou.edu -or- swingle@duce.cs.ohiou.edu *)
(* *)
(* or via regular U.S. mail: *)
(* Tom Swingle *)
(* 114 Grosvenor St. (campus address) *)
(* Athens, OH 45701 *)
(* *)
(* Tom Swingle *)
(* Rt. 1 Box 292 (After June, 1992) *)
(* Waterford, OH 45786 *)
(* *)
(* All code herein (except modifications made as noted) is the property *)
(* of the author, Copyright 1991. If this code is modified, all *)
(* modifications must be documented by the modifier before the code is *)
(* distributed. This file is not to be distributed if any portion of *)
(* this comment block has been removed. However, modifiers may add *)
(* modification comments into this comment block so long as all of the *)
(* additions are made after all other text in the block, and no text is *)
(* removed. All documentation and demonstration programs that came with *)
(* this file should be redistributed along with this file. *)
(* *)
(*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*)
interface
{$DEFINE NOCRT}
{ Remove the above line if you are using the CRT unit and do not want the
last four routines defined in the interface section to interfere with the
routines normally defined in the CRT unit. }
const
alt=132; { Alt + letter will return the character 132 above the letter }
home=#128; uparrow=#129; pgup=#130; { numeric }
leftarrow=#131; rightarrow=#132; { keypad }
end_=#133; downarrow=#134; pgdn=#135; { keys }
ins=#136; del=#137;
F1=#138; F2=#139; F3=#140; F4=#141; F5=#142;
F6=#143; F7=#144; F8=#145; F9=#146; F10=#147;
shiftF1=#148; shiftF2=#149; shiftF3=#150; shiftF4=#151; shiftF5=#152;
shiftF6=#153; shiftF7=#154; shiftF8=#155; shiftF9=#156; shiftF10=#157;
cntlF1=#158; cntlF2=#159; cntlF3=#160; cntlF4=#161; cntlF5=#162;
cntlF6=#163; cntlF7=#164; cntlF8=#165; cntlF9=#166; cntlF10=#167;
altF1=#168; altF2=#169; altF3=#170; altF4=#171; altF5=#172;
altF6=#173; altF7=#174; altF8=#175; altF9=#176; altF10=#177;
{ Regular, shifted, control, and alternate sets of function keys }
cntlhome=#183; cntlpgup=#178;
cntlleftarrow=#179; cntlrightarrow=#180;
cntlend=#181; cntlpgdn=#182; { Control + keypad keys }
alt1=#184; alt2=#185; alt3=#186; alt4=#187; alt5=#188;
alt6=#189; alt7=#190; alt8=#191; alt9=#192; alt0=#193;
{ Alt + numbers from top row of keyboard }
altminus=#194; altequal=#195; { Alt + "-" or "=" from middle of keyboard }
reversetab=#196; { Shift + tab key }
on=true; { Boolean constans for GetCapslock, GetNumLock, }
off=false; { GetScrollLock, SetCapsLock, SetNumLock, and SetScrollLock }
nonnumeric:boolean=false; { Disallow numbers on numeric keypad }
type charset=set of char;
var alttyped:boolean; { TRUE if the last key returned by getkey was entered
on the numeric keypad. This can be done by holding down the alt key and
typing the key's ASCII code on the numeric keypad. Undefined before the
first call to getkey. }
function getkey:char; { enhanced readkey }
procedure readno(var number:word; lobound,hibound:word);
procedure readint(var number:integer; lobound,hibound:integer);
procedure readreal(var number:real; lobound,hibound:real; decimals:byte);
{ Read an unsigned integer, signed integer, or real number between lobound
and hibound, and with maximum number of decimal places for real number. }
procedure readstr(var s:string; maxlen:byte; charstoexclude:charset);
{ Read a new string into s, starting with an empty string; allow no more
than maxlen chars; do not allow any characters in the charstoexclude set
to be entered into the string. }
procedure editstr(var s:string; maxlen:byte; charstoexclude:charset);
{ Edit the string currently in s; same rules as readstr. }
procedure flushbuffer; { Flush all typed-ahead keystrokes from buffer. }
procedure setcapslock(state:boolean); { Set the caps lock, num lock, }
procedure setnumlock(state:boolean); { scroll lock, or insert key state }
procedure setscrolllock(state:boolean); { on or off. State=TRUE means turn }
procedure setinsert(state:boolean); { on; state=FALSE means turn off. }
function getcapslock:boolean; { \ }
function getnumlock:boolean; { \Return current caps lock, num lock, }
function getscrolllock:boolean; { /scroll lock, or insert state. }
function getinsert:boolean; { / }
function screenwidth:byte; { Tell how many characters wide the screen is. }
function leftshiftdown:boolean; { Returns true if left shift key is down. }
function rightshiftdown:boolean; { Returns true if right shift key is down. }
function shiftdown:boolean; { Returns true if either shift key is down. }
function controldown:boolean; { Returns true if control key is down. }
function altdown:boolean; { Returns true if alt key is down. }
procedure chgcursor(startline,endline:byte);
{ Change the cursor so it starts at startline and ends at endline. }
{ Chgcursor ($20,0) will completely erase the cursor. }
procedure getcursor(var startline,endline:byte);
{ Get the current starting and ending line of the cursor. }
{$IFDEF NOCRT}
function keypressed:boolean; { Returns true if a key is waiting in buffer. }
function wherex:byte; { Returns x-coordinate of cursor. }
function wherey:byte; { Returns y-coordinate of cursor. }
procedure gotoxy(x,y:byte); { Positions cursor at (x,y). }
{$ENDIF}
implementation
uses dos;
var
keyflag:byte absolute $40:$17; { Location of keyboard status flags. }
scancode:byte; { Contains the scan code of last key pressed. }
{ Following are five routines normally defined in the CRT unit. Originally,
this unit was written using these routines directly from the CRT unit.
However, they have been rewritten using BIOS calls because the CRT unit
seems to be incompatible with text modes greater than 80 columns wide.
Four of them are included in the interface section so that programs using
this unit need not include the CRT unit in order to do basic keyboard
functions. A program using the CRT unit can call crt.keypressed,
crt.wherex, etc., if use of the CRT unit's routines is desired (or simply
remove the conditional compilation definition of NOCRT above. This is
probably unecessary because the routines are functionally equivalent, to
the best of my knowledge, except for one difference with keypressed.
Please read KEYBOARD.DOC for more details. }
function wherex:byte;
var regs:registers;
begin
regs.ah:=$F;
intr($10,regs); { Get correct display page into bh }
regs.ah:=3;
intr($10,regs); { Call BIOS int 10h, function 3--get cursor position }
wherex:=regs.dl+1;
end;
function wherey:byte;
var regs:registers;
begin
regs.ah:=$F;
intr($10,regs); { Get correct display page into bh }
regs.ah:=3;
intr($10,regs); { Call BIOS int 10h, function 3--get cursor position }
wherey:=regs.dh+1;
end;
procedure gotoxy(x,y:byte);
var regs:registers;
begin
regs.ah:=$F;
intr($10,regs); { Get correct display page into bh }
regs.ah:=2;
regs.dl:=x-1;
regs.dh:=y-1;
intr($10,regs); { Call BIOS int 10h, function 2--set cursor position }
end;
function keypressed:boolean;
{ Please read KEYBOARD.DOC for information on the additional side effect
that this function has. }
var regs:registers;
begin
repeat
regs.ah:=1;
intr($16,regs); { Call BIOS int 16h, function 1--check buffer status }
if (regs.flags and fzero=0) and (regs.ah=76) and nonnumeric
then begin { clear out keypad 5's in non-numeric mode }
regs.ah:=0;
intr($16,regs); { Call BIOS int 16h, function 0--get keystroke }
end;
until (regs.flags and fzero<>0) or (regs.flags and fzero=0) and
((regs.ah<>76) or not nonnumeric);
keypressed:=regs.flags and fzero=0; { ZF clear if keystroke waiting }
end;
function readkey:char;
var regs:registers;
begin
regs.ah:=0;
intr($16,regs); { Call BIOS int 16h, function 0--get keystroke }
readkey:=chr(regs.al);
scancode:=regs.ah; { global variable containing scan code of last key }
end;
procedure beep;
begin
{ Not implemented. Adding a beep without the CRT unit would require
appropriate Port out instructions, as well as a calibrated delay loop,
and the usefulness of a beep as a signal to the user is questionable, and
somewhat a matter of taste. If you care to add a beep to signal
incorrect input, put it here (remove this comment if you do). }
end;
function screenwidth;
var regs:registers;
begin
regs.ah:=$F;
intr($10,regs); { Call BIOS int 10h, function 15--get video mode }
screenwidth:=regs.ah;
end;
procedure backup(count:byte);
{ Back up the cursor a given number of spaces, allowing for backing up in
the leftmost column of the screen, which takes it to the row above }
var x,y:integer;
begin
x:=wherex; y:=wherey;
dec(x,count); { Back up the appropriate number of spaces }
while x<1 do begin { If it goes off the left edge, move to the row above }
inc(x,screenwidth);
dec(y);
end;
gotoxy(x,y);
end;
function getkey;
var
head:byte;
ch:char;
begin
repeat
ch:=readkey;
alttyped:=scancode=0;
{ A character typed on the numeric keypad will have a scan code of 0 }
if nonnumeric and (ch in ['0'..'9','.']) and (scancode>70) then begin
case ch of { Translate from number key to cursor control key }
'0':getkey:=ins;
'1':getkey:=end_;
'2':getkey:=downarrow;
'3':getkey:=pgdn;
'4':getkey:=leftarrow;
'6':getkey:=rightarrow;
'7':getkey:=home;
'8':getkey:=uparrow;
'9':getkey:=pgup;
'.':getkey:=del;
end;
if ch<>'5' then exit;
end;
until not((ch='5') and nonnumeric and (scancode>70));
if ch=#0 then begin { Special keys return an ASCII code=0. Process them. }
ch:=chr(scancode);
case ch of
#3: getkey:=#0; { null }
#15: getkey:=reversetab; { shift + tab key }
#59..#68: getkey:=chr(ord(ch)+79); { F1..F10 }
#84..#113: getkey:=chr(ord(ch)+64); { any other F key }
#71..#73: getkey:=chr(ord(ch)+57); { home, up arrow, pgup }
#75: getkey:=leftarrow;
#77: getkey:=rightarrow;
#79..#83: getkey:=chr(ord(ch)+54); { end, down arrow, pgdn, ins, del }
#115..#131:getkey:=chr(ord(ch)+64); { control+left arrow, right arrow,
end, pgdn, home; alt+1,2,...,9,0,_,= }
#132: getkey:=cntlpgup;
#16: getkey:=chr(alt+ord('Q'));
#17: getkey:=chr(alt+ord('W'));
#18: getkey:=chr(alt+ord('E'));
#19: getkey:=chr(alt+ord('R'));
#20: getkey:=chr(alt+ord('T'));
#21: getkey:=chr(alt+ord('Y'));
#22: getkey:=chr(alt+ord('U'));
#23: getkey:=chr(alt+ord('I'));
#24: getkey:=chr(alt+ord('O'));
#25: getkey:=chr(alt+ord('P'));
#30: getkey:=chr(alt+ord('A'));
#31: getkey:=chr(alt+ord('S'));
#32: getkey:=chr(alt+ord('D'));
#33: getkey:=chr(alt+ord('F'));
#34: getkey:=chr(alt+ord('G'));
#35: getkey:=chr(alt+ord('H'));
#36: getkey:=chr(alt+ord('J'));
#37: getkey:=chr(alt+ord('K'));
#38: getkey:=chr(alt+ord('L'));
#44: getkey:=chr(alt+ord('Z'));
#45: getkey:=chr(alt+ord('X'));
#46: getkey:=chr(alt+ord('C'));
#47: getkey:=chr(alt+ord('V'));
#48: getkey:=chr(alt+ord('B'));
#49: getkey:=chr(alt+ord('N'));
#50: getkey:=chr(alt+ord('M'));
end;
end else getkey:=ch; { If not #0, return ch as is }
end;
procedure readno;
var
i,maxlen:byte;
temp:longint;
ch:char;
s:string[5];
error:integer;
begin
if hibound<lobound then exit;
str(hibound,s);
maxlen:=length(s); { Figure maximum input width that can be needed }
repeat
s:=''; { Set s to null }
repeat { Get characters into s until ^M is pressed }
ch:=getkey;
case ch of
'0'..'9' : if length(s)<maxlen then begin
s:=s+ch;
write(ch)
end;
#8 : if length(s)>0 then begin
delete(s,length(s),1);
backup(1);
write(' ');
backup(1);
end;
#13 : if length(s)=0 then exit; { null string; no changes }
end
until ch=#13;
val(s,temp,error); { Now test number entered against bounds passed }
if (temp<lobound) or (temp>hibound) then begin
beep;
backup(length(s));
for i:=1 to length(s) do write(' ');
backup(length(s));
end;
until (temp>=lobound) and (temp<=hibound);
number:=temp;
end;
procedure readint;
var
i,maxlen:byte;
temp:longint;
ch:char;
s:string[6];
error:integer;
begin
if hibound<lobound then exit;
str(lobound,s);
maxlen:=length(s); { Maximum width needed is the width of the }
str(hibound,s); { lobound or the hibound, whichever is wider }
if length(s)>maxlen then maxlen:=length(s);
repeat { Same type of loop-within-loop as in previous procedure }
s:='';
repeat
ch:=getkey;
case ch of
'-' : if length(s)=0 then begin
s:='-'; { minus sign allowed if it is the first character in s }
write('-');
end;
'0'..'9' : if (length(s)<maxlen) then begin
s:=s+ch;
write(ch)
end;
#8 : if length(s)>0 then begin
delete(s,length(s),1);
backup(1);
write(' ');
backup(1);
end;
#13 : if length(s)=0 then exit;
end
until ch=#13;
val(s,temp,error);
if (temp<lobound) or (temp>hibound) then begin
beep;
backup(length(s));
for i:=1 to length(s) do write(' ');
backup(length(s));
end;
until (temp>=lobound) and (temp<=hibound);
number:=temp;
end;
procedure readreal;
var
i,maxlen:byte;
temp:real;
ch:char;
s:string;
error:integer;
begin
if hibound<lobound then exit;
str(lobound:1:decimals,s);
maxlen:=length(s); { Maximum width is the wider of the hibound and }
str(hibound:1:decimals,s); { the lobound with the appropriate decimals }
if length(s)>maxlen then maxlen:=length(s);
repeat { Again, same loop-within-loop }
s:='';
repeat
ch:=getkey;
case ch of
'-' : if length(s)=0 then begin
s:='-'; { minus sign allowed if it is the first character in s }
write('-');
end;
'.' : if (pos('.',s)=0) and (length(s)<maxlen) then begin
s:=s+'.'; { decimal pt. allowed if there is not already one in s }
write('.');
end;
'0'..'9' : if length(s)<maxlen then begin
s:=s+ch;
write(ch)
end;
#8 : if length(s)>0 then begin
delete(s,length(s),1);
backup(1);
write(' ');
backup(1);
end;
#13 : if length(s)=0 then exit;
end
until ch=#13;
val(s,temp,error);
if (temp<lobound) or (temp>hibound) then begin
beep;
backup(length(s));
for i:=1 to length(s) do write(' ');
backup(length(s));
end;
until (temp>=lobound) and (temp<=hibound);
number:=temp;
end;
procedure editstr;
var
regs:registers;
ch:char;
n,position,startline,endline:byte;
inson:boolean;
procedure update(noblanks,stepsback,startpos:byte);
{ Update the string, starting at position startpos. Stepsback contains how
many spaces to back up before starting the update. Noblanks contains how
many blanks to write after the updated string is written. After writing
the blanks (if any), the cursor is backed up to the end of the string. }
var
i:byte;
temp:string;
begin
temp:=copy(s,startpos,length(s)-startpos+1);
chgcursor($20,0);
backup(stepsback);
write(temp);
for i:=1 to noblanks do write(' ');
backup(length(temp)-stepsback+noblanks);
if inson then chgcursor(4,7) else chgcursor(6,7); { set cursor type }
end;
procedure addchar;
{ add the character ch to the string, only if:
- ch is not in the set charstoexclude of disallowed characters,
- ch is either less than #128 or has been typed on the numeric keypad (to
disallow special keys like F1 that are not trapped as editing keys), and
- there is room to insert the character (if in insert mode) or to add it
to the end of the string (if the cursor is at the end of the string) }
begin
if not (ch in charstoexclude) and (alttyped or (ch<#128))
and ((length(s)<maxlen) or not inson and (position<length(s))) then begin
write(ch);
if inson or (position=length(s)) then begin
insert(ch,s,position+1);
if position<length(s)-1 then update(0,0,position+2);
end else s[position+1]:=ch;
inc(position);
end; { echo the character, and insert it into the string if in insert mode
or overwrite the character at the cursor if in overstrike mode }
end;
begin
getcursor(startline,endline); { save cursor shape }
inson:=false; { overstrike mode at first }
chgcursor(6,7); { start with a thin cursor }
position:=length(s); { put cursor at end of string }
write(s); { write out the initial string }
charstoexclude:=charstoexclude+[^G,^J,^Z];
{ these characters won't display, so make sure they are excluded }
repeat
gotoxy(wherex,wherey); { This removed a problem with updating the cursor on
my screen, for some reason. Something in my ANSI driver, I think. }
ch:=getkey;
case ch of
^H : if (length(s)>0) and (position>0) then begin
delete(s,position,1);
update(1,1,position);
dec(position);
backup(1);
end; { backspace }
^I : if not alttyped and (position<length(s)-4) then begin
for n:=1 to 5 do if wherex=screenwidth
then gotoxy(1,wherey+1)
else gotoxy(wherex+1,wherey);
inc(position,5);
end; { tab key moves cursor forward five spaces }
^M : begin
chgcursor($20,0);
backup(position);
write(s);
end; { do final update before exiting }
^[ : begin
n:=length(s);
s:='';
update(n,position,1);
chgcursor($20,0);
backup(position);
position:=0;
if inson then chgcursor(4,7) else chgcursor(6,7);
end; { ESC key--clear out string }
ins : if alttyped then addchar else begin
inson:=not inson;
if inson then chgcursor(4,7) else chgcursor(6,7);
end;
del : if alttyped then addchar else
if (length(s)>0) and (position<length(s)) then begin
delete(s,position+1,1);
update(1,0,position+1);
end;
cntlhome : if alttyped then addchar else
if (length(s)>0) and (position>0) then begin
delete(s,1,position);
update(position,position,1);
chgcursor($20,0);
backup(position);
position:=0;
if inson then chgcursor(4,7) else chgcursor(6,7);
end; { delete from cursor to beginning of string }
cntlend : if alttyped then addchar else
if (length(s)>0) and (position<length(s)) then begin
n:=length(s)-position;
delete(s,position+1,n);
update(n,0,position+1);
end; { delete from cursor to end of string }
home : if alttyped then addchar else begin
chgcursor($20,0);
backup(position);
position:=0;
if inson then chgcursor(4,7) else chgcursor(6,7);
end;
end_ : if alttyped then addchar else begin
chgcursor($20,0);
backup(position);
write(s);
if inson then chgcursor(4,7) else chgcursor(6,7);
position:=length(s);
end;
reversetab: if not alttyped and (position>4) then begin
backup(5);
dec(position,5);
end; { reverse tab backs the cursor up five spaces }
leftarrow : if alttyped then addchar else if position>0 then begin
backup(1);
dec(position);
end;
rightarrow: if alttyped then addchar else if position<length(s) then begin
if wherex=screenwidth
then gotoxy(1,wherey+1) { wrap to next line if at end }
else gotoxy(wherex+1,wherey);
inc(position);
end;
uparrow: if alttyped then addchar else
if position>=screenwidth then begin
dec(position,screenwidth);
gotoxy(wherex,wherey-1);
end; { go up one line }
downarrow: if alttyped then addchar else
if position+screenwidth<=length(s) then begin
inc(position,screenwidth);
gotoxy(wherex,wherey+1);
end; { go down one line }
else addchar; { character is not an editing key, add it to the string }
end;
until ch=#13; { many keys have "if alttyped then addchar else ..." after
them; this means that if the key was typed on the numeric keypad, that it
should be taken literally and added to the string rather than being
interpreted as an editing key }
chgcursor(startline,endline); { restore cursor to the way it was }
end;
procedure readstr;
{ quite simple; just call editstr with an initially null string and return
the new string if it was changed }
var temp:string;
begin
temp:='';
editstr(temp,maxlen,charstoexclude);
if temp>'' then s:=temp;
end;
procedure flushbuffer;
var regs:registers;
begin
regs.ah:=$C;
regs.al:=0; { al=0 means don't do anything after flushing buffer }
msdos(regs); { Call DOS function 12--flush stdin buffer }
end;
{ The next four routines affect keyboard toggle states. They should be used
sparingly, if at all. The states are affected by toggling the appropriate
bit in the keyboard flag byte. }
procedure setcapslock;
begin
if state then keyflag:=keyflag or $40 else keyflag:=keyflag and $BF;
end;
procedure setnumlock;
begin
if state then keyflag:=keyflag or $20 else keyflag:=keyflag and $DF;
end;
procedure setscrolllock;
begin
if state then keyflag:=keyflag or $10 else keyflag:=keyflag and $EF;
end;
procedure setinsert;
begin
if state then keyflag:=keyflag or $80 else keyflag:=keyflag and $7F;
end;
function getcapslock;
var regs:registers;
begin
regs.ah:=2;
intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
getcapslock:=regs.al and 64=64; { Bit 6 contains caps lock status }
end;
function getnumlock;
var regs:registers;
begin
regs.ah:=2;
intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
getnumlock:=regs.al and 32=32; { Bit 5 contains num lock status }
end;
function getscrolllock;
var regs:registers;
begin
regs.ah:=2;
intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
getscrolllock:=regs.al and 16=16; { Bit 4 contains scroll lock status }
end;
function getinsert;
var regs:registers;
begin
regs.ah:=2;
intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
getinsert:=regs.al and 128=128; { Bit 7 contains insert status }
end;
function rightshiftdown;
var regs:registers;
begin
regs.ah:=2;
intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
rightshiftdown:=regs.al and 1=1; { Bit 0 contains right shift status }
end;
function leftshiftdown;
var regs:registers;
begin
regs.ah:=2;
intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
leftshiftdown:=regs.al and 2=2; { Bit 1 contains right shift status }
end;
function shiftdown;
var regs:registers;
begin
regs.ah:=2;
intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
shiftdown:=regs.al and 3<>0; { Check either bit 0 or 1 }
end;
function controldown;
var regs:registers;
begin
regs.ah:=2;
intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
controldown:=regs.al and 4=4; { Bit 2 contains control status }
end;
function altdown;
var regs:registers;
begin
regs.ah:=2;
intr($16,regs); { Call BIOS int 16h, function 2--get keyboard shift status }
altdown:=regs.al and 8=8; { Bit 3 contains alt status }
end;
procedure chgcursor;
var regs:registers;
begin
with regs do begin
ah:=1;
ch:=startline;
cl:=endline;
end;
intr($10,regs); { Call BIOS int 10h, function 1--set cursor shape }
end;
procedure getcursor;
var regs:registers;
begin
with regs do begin
ah:=$F;
intr($10,regs); { Get correct display page into bh }
ah:=3;
intr($10,regs); { Call BIOS int 10h, function 3--get cursor shape }
startline:=ch;
endline:=cl;
end;
end;
end.